Shader "FrameWork/Day24PBR"
{
    properties
    {
        _BaseMap("Base Map",2d) = "white"{}
        _BaseColor("Base Color",color) = (1,1,1,1)
        [Toggle(_ALPHATEST_ON)]_ALPHATEST_ON_Toggle("MyALPHATEST_ON_Toggle",float) = 1
        _Cutoff("Cut off",float) = 0.5
        [Enum(off,0,front,1,back,2)]_Cull("Cull",float) = 2
        
        [Toggle(_NORMALMAP)]_NormalMapToggle("Use NormalMap",float) = 0
        [NoScaleOffset]_BumpMap("Normal Map",2d) = "bump"{}
        [Toggle(_EMISSION)]_EmissionToggle("Use Emission",float) =0
        [HDR]_EmissionColor("Emission Color",Color) = (1,1,1,1)
        [NoScaleOffset]_EmissionMap("Emission Map",2d) = "white"{}

        [Toggle(_SPECGLOSSMAP)]_SpecGlossMapToggle("Use Specular Gloss Map",float) =0
        _SpecColor("Specular Color",Color) = (0.5,0.5,0.5,0.5)
        _SpecGlossMap("Specular Map",2d) = "white"{}
        [Toggle(_GLOSS_FROM_BASE_ALPHA)]_GlossSource("gloss source",float) = 0
        _Smoothness("Smoothness",Range(0.0,1.0)) = 0.5
    }
    
    subshader
    {
        Tags
        {
            "RenderPipeline" = "UniversalPipeline"
            "RenderType" = "Opaque"
            "Queue" = "Geometry"
        }
        
        HLSLINCLUDE
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            CBUFFER_START(UnityPerMaterial)
            float4 _BaseMap_ST;
            float4 _BaseColor;
            float _Cutoff;
            float4 _EmissionColor;
        
            float4 _SpecColor;
            float _Smoothness;
        
            CBUFFER_END
        ENDHLSL

        pass
        {
            Name "ForwardLit"
            Tags
            {
                "LightMode" = "UniversalForward"
            }
            Cull[_Cull]

            HLSLPROGRAM

            #include  "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #include  "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
            
            #pragma vertex SimpleLitPassVertex
            #pragma fragment SimpleLitPassFragment

            #pragma shader_feature _ALPHATEST_ON//变体开关
            #pragma shader_feature _NORMALMAP
            #pragma shader_feature _EMISSION
            #pragma shader_feature_local_fragment _SPECGLOSSMAP
            #define _SPECULAR_COLOR //总是打开高光颜色
            
            #pragma multi_compile LIGHTMAP_ON
            #pragma multi_compile _MAIN_LIGHT_SHADOWS
            #pragma multi_compile _MAIN_LIGHT_SHADOWS_CASCADE
            //#pragma multi_compile _ADDTIONAL_LIGHTS
            //#pragma multi_compile _ADDTIONAL_LIGHT_SHADOWS

            #pragma multi_compile _ADDITIONAL_LIGHTS
            #pragma multi_compile _ADDITIONAL_LIGHT_SHADOWS
            
            TEXTURE2D(_SpecGlossMap);SAMPLER(sampler_SpecGlossMap);
            
            struct Attributes
            {
                float4 posOS        :POSITION;
                float4 normalOS     :NORMAL;

                #ifdef _NORMALMAP
                    float4 tangentOS:TANGENT;
                #endif
                
                float2 uv           :TEXCOORD0;
                float2 lightmapUV   :TEXCOORD1;
                float4 color        :COLOR;
                
            };

            struct Varyings
            {
                float4 positionCS       :SV_POSITION;
                float2 uv               :TEXCOORD0;
                DECLARE_LIGHTMAP_OR_SH(lightmapUV,vertexSH,1);
                float3 positionWS       :TEXCOORD2;

                #ifdef _NORMALMAP
                    half4 normalWS      :TEXCOORD3;
                    half4 tangentWS     :TEXCOORD4;
                    half4 bitangentWS   :TEXCOORD5;
                #else
                    float3 normalWS     :TEXCOORD3;
                #endif

                //使用了额外的灯光。
                #ifdef _ADDTIONAL_LIGHT_VERTEX
                    half4 fogFactorAndVertexLight: TEXCOORD6;//x存的是wuxiao，yzw顶点光照
                #else
                    half fogFactor      : TEXCOORD6;    //有其他的可以填充
                #endif

                #ifdef REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR  //阴影坐标提前传入 不是算出
                    float4 shadowCoord  :TEXCOORD7;
                #endif
                float4 color         :COLOR;

            };

            //顶点空间切线
            Varyings SimpleLitPassVertex(Attributes IN)
            {
                Varyings OUT = (Varyings)0;
                VertexPositionInputs position_inputs = GetVertexPositionInputs(IN.posOS);
                OUT.positionCS = position_inputs.positionCS;
                OUT.positionWS = position_inputs.positionWS;

                //传法线切线
                #ifdef _NORMALMAP
                    VertexNormalInputs normal_inputs = GetVertexNormalInputs(IN.normalOS,IN.tangentOS);
                #else
                    VertexNormalInputs normal_inputs = GetVertexNormalInputs(IN.normalOS);
                #endif
                
                half3 viewDirWS = GetWorldSpaceViewDir(position_inputs.positionWS);

                //节省纹理坐标通道
                #ifdef _NORMALMAP
                    OUT.normalWS =half4(normal_inputs.normalWS,viewDirWS.x);
                    OUT.tangentWS =half4(normal_inputs.tangentWS,viewDirWS.y);
                    OUT.bitangentWS =half4(normal_inputs.bitangentWS,viewDirWS.z);
                #else
                    //为什么要这么做？
                    OUT.normalWS = NormalizeNormalPerVertex(normal_inputs.normalWS);
                #endif
                
                half fogFactor =ComputeFogFactor(position_inputs.positionCS.z);
                half3 vertexLight =VertexLighting(position_inputs.positionWS,normal_inputs.normalWS);

                #ifdef _ADDTIONAL_LIGHTS_VERTEX
                    OUT.fogFactorAndVertexLight =half4(fogFactor,vertexLight);
                #else
                    OUT.fogFactor =fogFactor;
                #endif

                
                #ifdef REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR
                    OUT.shadowCoord = GetShadowCoord(position_inputs);
                #endif
                
                OUTPUT_LIGHTMAP_UV(IN.lightmapUV,unity_LightmapST,OUT.lightmapUV);
                OUTPUT_SH(OUT.normalWS,OUT.vertexSH);
                OUT.uv = TRANSFORM_TEX(IN.uv,_BaseMap);
                OUT.color = IN.color;
                return OUT;
            }
            
            //unity的源码实现的
            half4 SampleSpecularSmoothness(float2 uv, half alpha, half4 specColor, TEXTURE2D_PARAM(specMap, sampler_specMap))
            {
                half4 specularSmoothness = half4(0, 0, 0, 1);
            #ifdef _SPECGLOSSMAP
                specularSmoothness = SAMPLE_TEXTURE2D(specMap, sampler_specMap, uv) * specColor;
            #elif defined(_SPECULAR_COLOR)
                specularSmoothness = specColor;
            #endif

            #ifdef _GLOSSINESS_FROM_BASE_ALPHA
                specularSmoothness.a = alpha;
            #endif

                return specularSmoothness;
            }
            
            /*
struct SurfaceData
{
    half3 albedo;
    half3 specular;
    half  metallic;
    half  smoothness;
    half3 normalTS;
    half3 emission;
    half  occlusion;
    half  alpha;
    half  clearCoatMask;
    half  clearCoatSmoothness;
};
             */
            void InitSurfaceData(Varyings IN,out SurfaceData surfaceData)
            {
                surfaceData = (SurfaceData)0;
                half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap,sampler_BaseMap,IN.uv);
                #ifdef _ALPHATEST_ON
                    clip(baseMap.a - _Cutoff);
                #endif
                half4 diffuse = baseMap * _BaseColor * IN.color;

                surfaceData.albedo =diffuse.rgb;
                surfaceData.normalTS = SampleNormal(IN.uv,_BumpMap,sampler_BumpMap);
                surfaceData.emission = SampleEmission(IN.uv,_EmissionColor,_EmissionMap,sampler_EmissionMap);
                surfaceData.occlusion = 1.0;

                half4 specular = SampleSpecularSmoothness(IN.uv,baseMap.a,_SpecColor,_SpecGlossMap,sampler_SpecGlossMap);
                surfaceData.specular = specular.rgb;
                surfaceData.smoothness = specular.a * _Smoothness;
            }

            void InitInputData(Varyings IN,half3 normalTS,out InputData inputData)
            {
                inputData = (InputData)0;
                
                inputData.positionWS =IN.positionWS;

                #ifdef _NORMALMAP
                    inputData.normalWS = TransformTangentToWorld(normalTS,half3x3(IN.tangentWS.xyz,
                        IN.bitangentWS.xyz,IN.normalWS.xyz));
                    half3 viewDirWS =half3(IN.normalWS.w ,IN.tangentWS.w,IN.bitangentWS.w);
                #else
                    inputData.normalWS = IN.normalWS;
                    half3 viewDirWS = GetWorldSpaceViewDir(IN.positionWS);
                #endif

                inputData.normalWS = NormalizeNormalPerPixel( inputData.normalWS);

                viewDirWS =SafeNormalize(viewDirWS);
                inputData.viewDirectionWS =viewDirWS;
 
                #ifdef REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR
                    inputData.shadowCoord =IN.shadowCoord;
                #elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
                    inputData.shadowCoord = TransformWorldToShadowCoord(IN.positionWS);
                #else
                    inputData.shadowCoord = float(0,0,0,0)
                #endif
                
                #ifdef _ADDTIONAL_LIGHTS_VERTEX
                    inputData.vertexLighting IN.fogFactorAndVertexLight.yzw;
                    inputData.fogCoord =IN.fogFactorAndVertexLight.x;
                #else
                    inputData.vertexLighting = half3(0,0,0);
                    inputData.fogCoord =IN.fogFactor.x;
                #endif
                
                inputData.bakedGI =SAMPLE_GI(IN.lightmapUV,IN.vertexSH,IN.normalWS);
                inputData.normalizedScreenSpaceUV =GetNormalizedScreenSpaceUV(IN.positionCS);
                inputData.shadowMask =SAMPLE_SHADOWMASK(IN.lightmapUV);
                
            }
            
            half4 SimpleLitPassFragment(Varyings IN) :SV_TARGET
            {
                SurfaceData surface_data;
                InitSurfaceData(IN,surface_data);
                InputData input_data;
                InitInputData(IN,surface_data.normalTS,input_data);
                half4 color = UniversalFragmentPBR(input_data,surface_data);
                return color;
            }
            
            ENDHLSL
        }
        
        Pass
        {
            Name "ShadowCaster"    
            Tags{"LightMode" = "ShadowCaster"}
            ZWrite On
            ZTest LEqual
            ColorMask 0
            Cull [_Cull]
                HLSLPROGRAM
                    #pragma shader_feature _ALPHATEST_ON
                    #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
                    #pragma multi_compile_instancing

                    #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW
                
                    #pragma  vertex ShadowPassVertex
                    #pragma  fragment ShadowPassFragment

                    #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
                    #include  "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
                    #include  "Assets/Day20阴影/CustomShaderPass.hlsl"
            ENDHLSL   
        }
        
        Pass
        {
            Name "DepthOnly"    
            Tags{"LightMode" = "DepthOnly"}
            ZWrite On
            ZTest LEqual
            ColorMask 0
            Cull [_Cull]
            
            HLSLPROGRAM
                    #pragma shader_feature _ALPHATEST_ON
                    #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
                    #pragma multi_compile_instancing

                    #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW
                
                    #pragma  vertex DepthOnlyVertex
                    #pragma  fragment DepthOnlyFragment

                    #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
                    #include  "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
                    #include  "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
            ENDHLSL   
        }
        
        //MSAA
        Pass
        {
            Name "DepthNormals"    
            Tags{"LightMode" = "DepthNormals"}
            ZWrite On
            ZTest LEqual
            ColorMask 0
            //Cull [_Cull]
            
            HLSLPROGRAM
                    #pragma shader_feature_local _NORMAL_MAP
                    #pragma shader_feature _ALPHATEST_ON
                    #pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
                    #pragma multi_compile_instancing

                    #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW
                
                    #pragma  vertex DepthNormalsVertex
                    #pragma  fragment DepthNormalsFragment

            

                    #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
                    #include  "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
                    #include  "Packages/com.unity.render-pipelines.universal/Shaders/DepthNormalsPass.hlsl"
            ENDHLSL   
        }
    }

    //Fallback  "Hidden/Universal Render Pipeline/FallbackError"
}
